/**
 * Copyright (C) 2021 - 2031 O-Cubes Co., Ltd.
 */

/****************************************************************
 *  @file    dw_i2c.h
 *  @brief   Designware i2c controller driver header file
 *  @version v1.0
 *  @date    03. Apr. 2023
 *  @author  liuchao
 ****************************************************************/

#ifndef __DW_I2C_H__
#define __DW_I2C_H__

#include <stdint.h>
#include "irq.h"
#include "dev_i2c.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
 * If this header file is included,
 * will indicate that this designware i2c device
 * is used
 */
#define DEVICE_USE_DESIGNWARE_I2C

#define DW_I2C_MASTER_SUPPORTED         (0x1)   /*!< Support Designware I2C Master Mode */
#define DW_I2C_SLAVE_SUPPORTED          (0x2)   /*!< Support Designware I2C Slave Mode */
/*!< Support Designware I2C Both Master and Slave Mode */
#define DW_I2C_BOTH_SUPPORTED           (DW_I2C_MASTER_SUPPORTED | DW_I2C_SLAVE_SUPPORTED)

#define DW_I2C_INVALID_INTNO            (DEV_INTNO_INVALID)

enum {
	DW_I2C_CAP_LOADING_100PF = 0,
	DW_I2C_CAP_LOADING_400PF
};

/**
 * @defgroup	DEVICE_DW_I2C_REGSTRUCT		DesignWare I2C Register Structure
 * @ingroup	DEVICE_DW_I2S
 * @brief	Structure definitions for DesignWare I2C register
 * @details	Detailed struct description of DesignWare I2C
 *	block register information, implementation of DEV_I2C_INFO::i2c_regs
 * @{
 */
typedef volatile struct dw_i2c_reg {
	uint32_t IC_CON;                /*!< (0x00) : I2C control */
	uint32_t IC_TAR;                /*!< (0x04) : I2C target address */
	uint32_t IC_SAR;                /*!< (0x08) : I2C slave address */
	uint32_t IC_HS_MADDR;           /*!< (0x0c) : I2C HS Master Mode Code address */
	uint32_t IC_DATA_CMD;           /*!< (0x10) : I2C Rx/Tx Data Buffer and Command */
	uint32_t IC_SS_SCL_HCNT;        /*!< (0x14) : Standard Speed I2C clock SCL High Count */
	uint32_t IC_SS_SCL_LCNT;        /*!< (0x18) : Standard Speed I2C clock SCL Low Count */
	uint32_t IC_FS_SCL_HCNT;        /*!< (0x1c) : Fast Speed I2C clock SCL Low Count */
	uint32_t IC_FS_SCL_LCNT;        /*!< (0x20) : Fast Speed I2C clock SCL Low Count */
	uint32_t IC_HS_SCL_HCNT;        /*!< (0x24) : High Speed I2C clock SCL Low Count */
	uint32_t IC_HS_SCL_LCNT;        /*!< (0x28) : High Speed I2C clock SCL Low Count */
	uint32_t IC_INTR_STAT;          /*!< (0x2c) : I2C Interrupt Status */
	uint32_t IC_INTR_MASK;          /*!< (0x30) : I2C Interrupt Mask */
	uint32_t IC_RAW_INTR_STAT;      /*!< (0x34) : I2C Raw Interrupt Status */
	uint32_t IC_RX_TL;              /*!< (0x38) : I2C Receive FIFO Threshold */
	uint32_t IC_TX_TL;              /*!< (0x3c) : I2C Transmit FIFO Threshold */
	uint32_t IC_CLR_INTR;           /*!< (0x40) : Clear combined and Individual Interrupts */
	uint32_t IC_CLR_RX_UNDER;       /*!< (0x44) : Clear RX_UNDER Interrupt */
	uint32_t IC_CLR_RX_OVER;        /*!< (0x48) : Clear RX_OVER Interrupt */
	uint32_t IC_CLR_TX_OVER;        /*!< (0x4c) : Clear TX_OVER Interrupt */
	uint32_t IC_CLR_RD_REQ;         /*!< (0x50) : Clear RQ_REQ Interrupt */
	uint32_t IC_CLR_TX_ABRT;        /*!< (0x54) : Clear TX_ABRT Interrupt */
	uint32_t IC_CLR_RX_DONE;        /*!< (0x58) : Clear RX_DONE Interrupt */
	uint32_t IC_CLR_ACTIVITY;       /*!< (0x5c) : Clear ACTIVITY Interrupt */
	uint32_t IC_CLR_STOP_DET;       /*!< (0x60) : Clear STOP_DET Interrupt */
	uint32_t IC_CLR_START_DET;      /*!< (0x64) : Clear START_DET Interrupt */
	uint32_t IC_CLR_GEN_CALL;       /*!< (0x68) : Clear GEN_CALL Interrupt */
	uint32_t IC_ENABLE;             /*!< (0x6c) : I2C Enable */
	uint32_t IC_STATUS;             /*!< (0x70) : I2C Status */
	uint32_t IC_TXFLR;              /*!< (0x74) : Transmit FIFO Level Register */
	uint32_t IC_RXFLR;              /*!< (0x78) : Receive FIFO Level Register */
	uint32_t IC_SDA_HOLD;           /*!< (0x7c) : SDA Hold Time Length Reg */
	uint32_t IC_TX_ABRT_SOURCE;     /*!< (0x80) : I2C Transmit Abort Status Reg */
	uint32_t IC_SLV_DATA_NACK_ONLY; /*!< (0x84) : Generate SLV_DATA_NACK Register */
	uint32_t IC_DMA_CR;             /*!< (0x88) : DMA Control Register */
	uint32_t IC_DMA_TDLR;           /*!< (0x8c) : DMA Transmit Data Level */
	uint32_t IC_DMA_RDLR;           /*!< (0x90) : DMA Receive Data Level */
	uint32_t IC_SDA_SETUP;          /*!< (0x94) : SDA Setup Register */
	uint32_t IC_ACK_GENERAL_CALL;   /*!< (0x98) : ACK General Call Register */
	uint32_t IC_ENABLE_STATUS;      /*!< (0x9c) : Enable Status Register */
	uint32_t IC_FS_SPKLEN;          /*!< (0xa0) : ISS and FS spike suppression limit */
	uint32_t IC_HS_SPKLEN;          /*!< (0xa4) : HS spike suppression limit */
	uint32_t RESERVED[19];          /*!< (0xa8) : Reserved */
	uint32_t IC_COMP_PARAM_1;       /*!< (0xf4) : Component Parameter Register */
	uint32_t IC_COMP_VERSION;       /*!< (0xf8) : Component Version ID Reg */
	uint32_t IC_COMP_TYPE;          /*!< (0xfc) : Component Type Reg */
} DW_I2C_REG, *DW_I2C_REG_PTR;
/** @} */

/** Spike Suppression Limit Configurations */
typedef struct dw_i2c_spklen {
	uint32_t fs_spklen;     /*!< value for IC_FS_SPKLEN, Tsp for fast mode is 50ns */
	uint32_t hs_spklen;     /*!< value for IC_HS_SPKLEN, Tsp for high-speed mode is 10ns */
} DW_I2C_SPKLEN, *DW_I2C_SPKLEN_PTR;

/** I2C Clock SCL High and Low Count Configurations for Different Speed */
typedef struct dw_i2c_scl_cnt {
	uint32_t ss_scl_hcnt;   /*!< value for IC_SS_SCL_HCNT */
	uint32_t ss_scl_lcnt;   /*!< value for IC_SS_SCL_LCNT */
	uint32_t fs_scl_hcnt;   /*!< value for IC_FS_SCL_HCNT */
	uint32_t fs_scl_lcnt;   /*!< value for IC_FS_SCL_LCNT */
	uint32_t hs_scl_hcnt;   /*!< value for IC_HS_SCL_HCNT */
	uint32_t hs_scl_lcnt;   /*!< value for IC_HS_SCL_LCNT */
} DW_I2C_SCL_CNT, *DW_I2C_SCL_CNT_PTR;

#define DW_I2C_GINT_DISABLED            (0)             /*!< designware interrupt disabled for control i2c irq/fiq */
#define DW_I2C_GINT_ENABLE              (1 << 0)        /*!< designware interrupt enabled for control i2c irq/fiq */
#define DW_I2C_TXINT_ENABLE             (1 << 1)        /*!< designware interrupt enabled for control transmit process */
#define DW_I2C_RXINT_ENABLE             (1 << 2)        /*!< designware interrupt enabled for control transmit process */

typedef struct dw_i2c_buffer {
	DEV_BUFFER *buf;
	uint32_t ofs;
	uint32_t len;
} DW_I2C_BUFFER, *DW_I2C_BUFFER_PTR;

/// I2C configure data structure
typedef struct {
	/// I2C Device ID
	uint32_t i2c_devid;
	/// IIC Bus speed mode
	I2C_SPEED_MODE i2c_speed_mode;
	/// I2C Device mode, master or slave
	uint32_t i2c_mode;
	/// Target slave address when working as master
	uint32_t tar_addr;
	/// IIC Addressing Mode, 7bit or 10bit
	I2C_ADDRESS_MODE i2c_addr_mod;
} DW_I2C_CFG;

/**
 * @brief	DesignWare I2C control structure definition
 * @details	implement of dev_i2c_info::i2c_ctrl
 */
typedef struct dw_i2c_ctrl {
	uint32_t i2c_id;                        /*!< i2c id */
	DW_I2C_REG *dw_i2c_regs;                /*!< i2c device registers */
	/* Variables which should be set during object implementation */
	uint32_t ic_clkhz;                      /*!< IC clock in HZ */
	uint32_t ic_caploading;                 /*!< I2C Bus cap loading pf */
	uint32_t support_modes;                 /*!< supported i2c modes */
	uint32_t tx_fifo_len;                   /*!< transmit fifo length */
	uint32_t rx_fifo_len;                   /*!< receive fifo length */
	uint32_t i2c_master_code;               /*!< value for IC_HS_MADDR */
	uint32_t retry_cnt;                     /*!< retry count for TX or RX */
	uint32_t intno;                         /*!< i2c interrupt vector number */
	irq_handler dw_i2c_int_handler;       /*!< i2c interrupt handler */
	DW_I2C_SPKLEN i2c_spklen;               /*!< i2c spike suppression length settings */
	DW_I2C_SCL_CNT i2c_scl_cnt;             /*!< i2c scl count settings */
	/* Variables which always change during i2c operation */
	uint32_t int_status;                    /*!< i2c interrupt status */
	uint32_t i2c_tx_over;                   /*!< i2c tx overflow count */
	uint32_t i2c_rx_over;                   /*!< i2c rx overflow count */
	DW_I2C_BUFFER dw_i2c_rxbuf;             /*!< i2c read buffer for receive data */
} DW_I2C_CTRL, *DW_I2C_CTRL_PTR;

/*!< One possible value for \ref dw_i2c_ctrl::retry_cnt */
#define DW_I2C_MAX_RETRY_COUNT                  (0x10000)

#define DW_I2C_FS_SPKLEN_NS                     (50)
#define DW_I2C_HS_SPKLEN_NS                     (10)

#define MIN_DW_I2C_SS_SCL_LCNT(spklen)          ((spklen) + 7)
#define MIN_DW_I2C_FS_SCL_LCNT(spklen)          ((spklen) + 7)

#define MIN_DW_I2C_SS_SCL_HCNT(spklen)          ((spklen) + 5)
#define MIN_DW_I2C_FS_SCL_HCNT(spklen)          ((spklen) + 5)

#define MIN_DW_I2C_HS_SCL_LCNT(spklen)          ((spklen) + 7)
#define MIN_DW_I2C_HS_SCL_HCNT(spklen)          ((spklen) + 5)

#define MIN_DW_I2C_SS_HIGH_TIME_NS              (4000)
#define MIN_DW_I2C_SS_LOW_TIME_NS               (4700)

#define MIN_DW_I2C_FS_HIGH_TIME_NS              (600)
#define MIN_DW_I2C_FS_LOW_TIME_NS               (1300)

#define MIN_DW_I2C_HS_100PF_HIGH_TIME_NS        (60)
#define MIN_DW_I2C_HS_100PF_LOW_TIME_NS         (160)

#define MIN_DW_I2C_HS_400PF_HIGH_TIME_NS        (120)
#define MIN_DW_I2C_HS_400PF_LOW_TIME_NS         (320)

int32_t dw_i2c_open(DEV_I2C *i2c_dev, uint32_t mode, uint32_t param);
int32_t dw_i2c_close(DEV_I2C *i2c_dev);
int32_t dw_i2c_control(DEV_I2C *i2c_dev, uint32_t ctrl_cmd, void *param);
int32_t dw_i2c_write(DEV_I2C *i2c_dev, const void *data, uint32_t len);
int32_t dw_i2c_read(DEV_I2C *i2c_dev, void *data, uint32_t len);
int32_t dw_i2c_dma_write(DEV_I2C *i2c_dev, const void *data, uint32_t len);
int32_t dw_i2c_dma_read(DEV_I2C *i2c_dev, const void *w_buf, uint32_t w_len, void *r_buf, uint32_t r_len);
void dw_i2c_isr(DEV_I2C *i2c_dev, void *ptr);

#ifdef __cplusplus
}
#endif

#endif /* __DW_I2C_H__ */
